<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
    function work(a, b) {
        console.log( a + b ); // work 是一个任意的函数或方法
    }


    function spy_my(f){
        //其实不用在这里声明一个类型的全局变量 可以把这个变量定义在record身上，使用NFE类调用
        let arr =[]
        function  record(){
          arr.push(Array.prototype.join.call(arguments))
        }

        record.call =arr
        return record
    }

    work = spy_my(work)
    work(1,2)
    work(3,4)

    // for (const arrayElement of work.call) {
    //     console.log(arrayElement)
    // }

    //在这里可以看出装饰器不仅可以在目标函数的调用之前和调用之后做一些操作 也可以为目标函数身上定义一些东西
    function spy(func) {
        function wrapper(...args) {
            // using ...args instead of arguments to store "real" array in wrapper.calls
            wrapper.calls.push(args);
            return func.apply(this, args);
        }

        //这里的代码写在上面也是可以的
        //因为当调用spy()的时候在预编译的阶段就会定义wrapper然后再在wrapper身上绑定一个calls
        wrapper.calls = [];

        return wrapper;

    }



    work = spy(work);

    work(1, 2); // 3
    work(4, 5); // 9

    // for (let args of work.calls) {
    //     console.log( 'call:' + args.join() ); // "call:1,2", "call:4,5"
    // }



    //装饰器还可以按照一定的方式来调用我们的函数 比如这里用定时器调用我们的函数
    function delay(f, ms) {
        return function(...args) {
            let savedThis = this; // 将 this 存储到中间变量
            setTimeout(function() {
                f.apply(savedThis, args); // 在这儿使用它
            }, ms);
        };

    }

    /*
    *
    * 如果我们这里延时调用的是一个有返回值的函数的话就要考虑通过回调函数进行传值了
    * */
    function delay_pro(f,ms){
        return function (fn,...args){
            setTimeout(()=>{
                let res = f.apply(this,args)
                //这里不能将返回值进行return因为计时器是没有返回值的而且这里是一个异步调用所以只能通过回调函数来传值
                /*
                * 对比这里的回调函数和map函数里面的回调
                * */
                fn(res)
            },ms)
        }
    }

    function foo1(a,b){
        return a+b
    }

    foo1 = delay_pro(foo1,1000)
    foo1(res =>{
        console.log(res)
    },1,2)



</script>
</body>
</html>